﻿using SewerAPI.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using SewerAPI.Core;
using System.Diagnostics;
using System.Threading;
using SewerAPI.Security;

namespace SewerAPITest
{
    
    
    /// <summary>
    ///This is a test class for ServerTest and is intended
    ///to contain all ServerTest Unit Tests
    ///</summary>
    [TestClass()]
    public class IOTest
    {


        private TestContext testContextInstance;
        private Server server;
        private Client client;
        private bool wait = false;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        [TestInitialize()]
        public void MyTestInitialize()
        {
            server = new Server();
            client = new Client();
        }
        //
        //Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup()
        {
            wait = false;
            //server.Dispose();
            //client.Dispose();
        }
        //
        #endregion


        /// <summary>
        ///A test for PerformTransaction
        ///</summary>
        [TestMethod()]
        public void ServerTest()
        {
            Message m = SecurityTest.GetTestMessage();
            server.OnSucces += new SuccesTransactionHandler(target_OnSuccesServer);
            server.Transact(m);           
        }

        [TestMethod()]
        public void ClientReceiveTest()
        {
            client.OnBytesReceived += new BytesReceived(target_OnBytesReceived);
            client.OnSucces += new SuccesTransactionHandler(target_OnSuccesClient);
            client.OnFail += new FailedTransactionHandler(target_OnFail);
            client.StartListening();
            //Send a test message
            server.Transact(SecurityTest.GetTestMessage());
            //Set the flag
            wait = true;
            whaitFor();
        }

        #region Util Method
        
        /// <summary>
        /// Whait for method
        /// </summary>
        private void whaitFor()
        {
            int _elapsedtime = 0;
            int _lagtime = 2000;
            int _sleeptime = 1;
            //
            if (wait)
            {
                while (wait && _elapsedtime < _lagtime)
                {
                    Thread.Sleep(_sleeptime);
                    _elapsedtime += _sleeptime;
                }
                if (!wait) { Trace.WriteLine("Whait flag was set to true"); }
                else { Trace.WriteLine(string.Format("Lagtime exceeded ({0}s)",_lagtime/1000)); }
                wait = false;
            }
        }

        #endregion

        #region Event Handlers

        void target_OnBytesReceived(byte[] received, IAsyncResult result)
        {
            //The encryption engine
            StandardEncryptionEngine _e = new StandardEncryptionEngine();
            //The test parameters
            string _expected = SecurityTest.GetTestMessage().Text;
            string _actual = _e.DecryptMessage(received).Text;
            //Compare them
            Trace.WriteLine((_expected.Equals(_actual)) ? "Data correctly received" : "Data not equal");
            //Reset flag
            wait = false;
        }

        void target_OnFail(Message m, TransactionArgs e)
        {
            Trace.WriteLine("Failed");
            wait = true;
        }

        void target_OnSuccesServer(Message m, TransactionArgs e)
        {
            Trace.WriteLine("Server reported a successful sent message");
            Trace.WriteLine("Message: " + m.Text);
            Trace.WriteLine("IPE: " + m.To.ToString());
            Trace.WriteLine("Args: " + e.State);
        }

        void target_OnSuccesClient(Message m, TransactionArgs e)
        {
            Trace.WriteLine("Client reported a successful received message");
            Trace.WriteLine("Message: " + m.Text);
            Trace.WriteLine("IPE: " + m.To.ToString());
            Trace.WriteLine("Args: " + e.State);
            wait = true;
        }

        #endregion
    }
}
